<?php
declare (strict_types = 1);

namespace app\middleware;

use think\facade\Cache;
use think\facade\Env;

class ApiSign
{
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure       $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        /*********************** 验证AppKey参数 ******************/
        $headers = $request->header();
        if (!isset($headers["app-key"])) {
            return json(["code" => 400, "msg" => "秘钥参数缺失"]);
        }
        $reqAppKey = $headers["app-key"];
        $vfyAppKey = Env::get("APISETTINGS.APP_KEY");
        if ($reqAppKey != $vfyAppKey) {
            return json(["code" => 400, "msg" => "签名秘钥无效"]);
        }

        /*********************** 验证时间戳参数 *******************/
        $params = $request->param();
        if (!isset($params["timestamp"])) {
            return json(["code" => 400, "msg" => "时间参数缺失"]);
        }
        $timestamp = $params["timestamp"];
        $nowTime = time();
        if (($nowTime-$timestamp) > 2) {
            return json(["code" => 400, "msg" => "时间参数过期"]);
        }

        /*********************** 验证签名串参数 *******************/
        if (!isset($params["sign"])) {
            return json(["code" => 400, "msg" => "签名参数缺失"]);
        }
        $reqSign = $params["sign"];
        unset($params["sign"]);
        // 将参数进行排序
        ksort($params);
        $paramStr = http_build_query($params);//构建一个 URL 的查询字符串://nonce_str=HJ8P8er9hFBiDtC4epTZFZPiBjB14e5p×tamp=1721359240&user_id=1001
        // md5 加密处理
        $vfySign = md5($paramStr . "&app_key={$vfyAppKey}");
        // 比较签名参数
        if ($reqSign != $vfySign) {
            return json(["code" => 400, "msg" => "签名验证失败"]);
        }

        /*********************** 验证随机串参数 *******************/
        if (!isset($params["nonce_str"])) {
            return json(["code" => 400, "msg" => "随机串参数缺失"]);
        }
        $nonceStr = $params["nonce_str"];

        // 判断 nonce_str 随机字符串是否被使用
        $flag = Cache::store('redis')->exists($nonceStr);
        if ($flag) {
            return json(["code" => 400, "msg" => "随机串参数无效"]);
        }

        // 存储 nonce_str 随机字符串
        Cache::store('redis')->set($nonceStr, $timestamp, 2);

        return $next($request);
    }
}
